#ifndef NETLIB_LOGGER_H
#define NETLIB_LOGGER_H

// 日志类
// Logger -> Impl -> LogStream -> operator<< -> FixedBuffer -> g_output -> g_flush

#include "LogStream.h"
#include "Timestamp.h"
#include"LogFile.h"

namespace netlib
{

class TimeZone;

class Logger
{
public:
    enum LogLevel // 日志等级枚举，从详细到粗略
    {
        TRACE,
        DEBUG,
        INFO,
        WARN,
        ERROR,
        FATAL,
        NUM_LOG_LEVELS,
    };

    
    class SourceFile // 内嵌类 文件名称类
    {
    public:
        template<int N> // N非类型参数
        SourceFile(const char (&arr)[N])
            : data_(arr),
              size_(N-1)
        {
            // strrchr(char* buf,int ch)返回字符串中ch最后出现的位置
            const char* slash = strrchr(data_, '/'); // builtin function
            if (slash)
            {
                data_ = slash + 1;
                size_ -= static_cast<int>(data_ - arr);
            }
        }

        explicit SourceFile(const char* filename)
        : data_(filename)
        {
            const char* slash = strrchr(filename, '/');
            if (slash)
                data_ = slash + 1;
            size_ = static_cast<int>(strlen(data_));
        }

        const char* data_;      // 文件名称
        int size_;              // 名称长度

    }; // class SourceFile end

    // file文件名称，line代码所在行号，level日志等级，func函数名称，toAbort是否退出程序
    Logger(SourceFile file, int line);
    Logger(SourceFile file, int line, LogLevel level);
    Logger(SourceFile file, int line, LogLevel level, const char* func);
    Logger(SourceFile file, int line, bool toAbort);
    ~Logger();

    LogStream& stream() { return impl_.stream_; } // 返回一个IO对象

    static LogLevel logLevel(); // 返回当前对象的日志等级

    static void setLogLevel(LogLevel level); // 设置当前对象的日志等级

    typedef void (*OutputFunc)(const char* msg, int len);   // 函数指针，输出流函数
    typedef void (*FlushFunc)();                            // 函数指针，

    static void setOutput(OutputFunc); // 设置输出流

    static void setFlush(FlushFunc); // 设置冲洗缓冲区的位置

    static void setTimeZone(const TimeZone& tz); // 

private:

    class Impl // 内嵌类 用于返回一个IO对象
    {
    public:
        typedef Logger::LogLevel LogLevel; // 日志等级枚举

        // old_errno，errno错误码
        Impl(LogLevel level, int old_errno, const SourceFile& file, int line);

        void formatTime(); // 格式化时间

        void finish();

        Timestamp time_;            // 记录日志时间
        LogStream stream_;          // 日志IO流
        LogLevel level_;            // 日志等级
        int line_;                  // 代码行号
        SourceFile basename_;       // 文件名

    }; // class Impl end

    Impl impl_;

}; // class Logger end

extern Logger::LogLevel g_logLevel; // 日志等级变量声明

// 返回当前日志对象的日志等级
inline Logger::LogLevel Logger::logLevel() { return g_logLevel; }


// 宏定义匿名对象，__FILE__文件名称，__LINE__代码行号，logLevel日志等级，__func__函数名称

#define LOG_TRACE if (netlib::Logger::logLevel() <= netlib::Logger::TRACE) \
  netlib::Logger(__FILE__, __LINE__, netlib::Logger::TRACE, __func__).stream()
#define LOG_DEBUG if (netlib::Logger::logLevel() <= netlib::Logger::DEBUG) \
  netlib::Logger(__FILE__, __LINE__, netlib::Logger::DEBUG, __func__).stream()
#define LOG_INFO if (netlib::Logger::logLevel() <= netlib::Logger::INFO) \
  netlib::Logger(__FILE__, __LINE__).stream()
#define LOG_WARN netlib::Logger(__FILE__, __LINE__, netlib::Logger::WARN).stream()
#define LOG_ERROR netlib::Logger(__FILE__, __LINE__, netlib::Logger::ERROR).stream()
#define LOG_FATAL netlib::Logger(__FILE__, __LINE__, netlib::Logger::FATAL).stream()
#define LOG_SYSERR netlib::Logger(__FILE__, __LINE__, false).stream()
#define LOG_SYSFATAL netlib::Logger(__FILE__, __LINE__, true).stream() // true 将推出程序

const char* strerror_tl(int savedErrno); // 获得错误码的详细描述


#define CHECK_NOTNULL(val) \
  ::netlib::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))


template <typename T>
T* CheckNotNull(Logger::SourceFile file, int line, const char *names, T* ptr)
{
    if (ptr == NULL)
        Logger(file, line, Logger::FATAL).stream() << names;
    return ptr;
}

} // namespace netlib end

#endif